/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Creer_Rejoindre_Groupe;

import Objets.Groupe;
import Objets.Pair;
import Objets.SuperPair;
import java.io.*;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.AdvertisementFactory;
import net.jxta.document.Document;
import net.jxta.document.MimeMediaType;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.MessageElement;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.exception.JxtaException;
import net.jxta.exception.PeerGroupException;
import net.jxta.id.IDFactory;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupFactory;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.pipe.*;
import net.jxta.platform.Module;
import net.jxta.protocol.ModuleImplAdvertisement;
import net.jxta.protocol.PeerGroupAdvertisement;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.util.AdvertisementUtilities;

/**
 *
 * @author Nono
 */
public class CreerRejoindreGroupe2 implements PipeMsgListener, OutputPipeListener {

    static PeerGroup jxtaConfig = null;    // my initial group
    private DiscoveryService discoSvc;
    private PipeService pipe;
    private PipeAdvertisement pipeSuperAdv = null;
    private String nomGroupe = "";
    private PeerGroup subgroup = null;
    private InputPipe pipeIn = null;
    private boolean hasResponse = false;
    private String messageResponse = "";
    private String pipePriveName = "pipe_prive2.adv";
    private String pipeGroupeName = "pipe_groupe2.adv";

    public static void main(String args[]) throws InterruptedException, IOException, JxtaException {

        System.out.println("Rejoindre / Creer un groupe");
        CreerRejoindreGroupe2 myapp = new CreerRejoindreGroupe2();

        myapp.startJxta();
        String nomGroupe;

        System.out.print("Veuillez entrer un nom de groupe : ");
        BufferedReader dis = new BufferedReader(new InputStreamReader(System.in));
        nomGroupe = dis.readLine();

        myapp.setNomGroupe(nomGroupe);

        myapp.sendMessageToEntree();
        myapp.receiveMessageFromEntree();

        Thread.sleep(5000); // On attend 5 secondes les réponses

        boolean hasResponse = myapp.getHasResponse();
        // Si on a eu que des réponses "false" , le groupe n'existe pas
        if (!hasResponse) {
            System.out.println("Je crée le groupe, je suis superpair");
            myapp.createJoinGroup(); // Creer le groupe
            myapp.closePipe(); // Close le pipe d'entree
            myapp.createSuperPair(); // Creer le super pair avec les pipes qui vont bien
        } else { // Si on n'est pas banni
            String messageResponse = myapp.getMessageResponse();
            String str[] = messageResponse.split(" ");
            if (str[0].equals("repgroupe") && str[1].equals("authorized")) { // Si on est pas ban 
                System.out.println("Je rejoins le groupe, je suis pair et je ne suis pas ban");
                myapp.createJoinGroup();// Rejoins le groupe        
                myapp.closePipe(); // Close le pipe d'entree
                myapp.createPair(str); // Creer le pair
            } else if (str[0].equals("repgroupe") && str[1].equals("denied")) {
                System.out.println("Impossible de rejoindre le groupe : vous êtes banni.");
            } else {
                System.out.println("J'ai rien compris à ce que j'ai recu");
            }
        }
    }

    private void startJxta() {
        try {
            // create, and Start the default jxta NetPeerGroup
            jxtaConfig = PeerGroupFactory.newNetPeerGroup();
        } catch (PeerGroupException e) {
            // could not instantiate the group, print the stack and exit
            System.out.println("Erreur : Config de jxta planted");
            e.printStackTrace();
            System.exit(1);
        }

        // Extract the discovery service from our peer group
        discoSvc = jxtaConfig.getDiscoveryService();

        // get the pipe service, and discovery
        pipe = jxtaConfig.getPipeService();
        try {
            FileInputStream is = new FileInputStream("pipe_entree.adv");
            pipeSuperAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8, is);
            is.close();
        } catch (Exception e) {
            System.out.println("failed to read/parse pipe advertisement");
            e.printStackTrace();
            System.exit(-1);
        }
    }

    @Override
    public void pipeMsgEvent(PipeMsgEvent event) {
        Message msg = null;
        try {
            // grab the message from the event
            msg = event.getMessage();
            if (msg == null) {
                return;
            } else {
                String msgContent = "";
                Message.ElementIterator it = msg.getMessageElements();

                while (it.hasNext()) {
                    MessageElement el = (MessageElement) it.next();
                    msgContent = el.getElementName();
                }

                if (!msgContent.equals(jxtaConfig.getPeerName() + " groupe " + nomGroupe)) {
                    System.out.println("------------------Message Receive---------------------");
                    System.out.println("Message : " + msgContent);
                    System.out.println("-------------------End of Message---------------------");
                    hasResponse = true;
                    messageResponse = msgContent;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

    /**
     * by implementing OutputPipeListener we must define this method which is
     * called when the output pipe is created
     *
     * @param event event object from which to get output pipe object
     */
    public void outputPipeEvent(OutputPipeEvent event) {

        OutputPipe op = event.getOutputPipe();
        Message msg = null;

        try {
            msg = new Message();
            Date date = new Date(System.currentTimeMillis());
            StringMessageElement sme = new StringMessageElement(jxtaConfig.getPeerName() + " groupe " + nomGroupe, date.toString(), null);
            msg.addMessageElement(null, sme);
            op.send(msg);
        } catch (IOException e) {
            System.out.println("failed to send message");
            e.printStackTrace();
            System.exit(-1);
        }
        op.close();
    }

    public void setNomGroupe(String nomGroupe) {
        this.nomGroupe = nomGroupe;
    }

    public String getNomGroupe() {
        return this.nomGroupe;
    }

    public void sendMessageToEntree() {
        try {
            pipe.createOutputPipe(pipeSuperAdv, this);
        } catch (IOException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void receiveMessageFromEntree() {
        try {
            pipeIn = pipe.createInputPipe(pipeSuperAdv, this);
        } catch (IOException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void closePipe() {
        pipeIn.close();
    }

    private boolean getHasResponse() {
        return hasResponse;
    }

    private String getMessageResponse() {
        return messageResponse;
    }

    private void createJoinGroup() {
        // Connect to our subgroup (all groups are subgroups of Netgroup)
        // If the group does not exist, it will be automatically created
        // Note this is suggested deprecated, not sure what the better way is
        ModuleImplAdvertisement mAdv = null;
        try {
            mAdv = jxtaConfig.getAllPurposePeerGroupImplAdvertisement();
        } catch (Exception ex) {
            System.err.println(ex.toString());
        }

        String subgroup_name = nomGroupe;
        String subgroup_desc = "...";
        PeerGroupID subgroup_id = IDFactory.newPeerGroupID(PeerGroupID.defaultNetPeerGroupID, subgroup_name.getBytes());
        try {
            subgroup = jxtaConfig.newGroup(subgroup_id, mAdv, subgroup_name, subgroup_desc);
        } catch (PeerGroupException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }

        // A simple check to see if connecting to the group worked
        if (Module.START_OK != subgroup.startApp(new String[0])) {
            System.err.println("Cannot start child peergroup");

        } else {
            System.out.println("Join / Creation ok ");
            PeerGroupAdvertisement adv = subgroup.getPeerGroupAdvertisement();
            PeerGroupID GID = adv.getPeerGroupID();
        }
    }

    private PipeAdvertisement createPipeAdv(String id, String type, String name) throws JxtaException {
        PipeAdvertisement pipeAdvTemp = AdvertisementUtilities.createPipeAdvertisement(id, name);
        pipeAdvTemp.setName(type);
        Document doc = pipeAdvTemp.getDocument(MimeMediaType.XMLUTF8);
        try {
            FileWriter writer = new FileWriter("pipe_groupe_created.adv");
            writer.write(doc.toString());
            writer.flush();
            writer.close();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        return pipeAdvTemp;
    }

    private void createSuperPair() throws IOException {

        // Création d'un pipe privé
        PipeAdvertisement pipePriveAdv = null;
        FileInputStream is1;
        try {
            is1 = new FileInputStream(pipePriveName);
            pipePriveAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8, is1);
            is1.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Création d'un pipe de groupe
        PipeAdvertisement pipeGroupeAdv = null;
        FileInputStream is2;
        try {
            is2 = new FileInputStream(pipeGroupeName);
            pipeGroupeAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8, is2);
            is2.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }

        SuperPair superpair = new SuperPair(jxtaConfig.getPeerName());
        superpair.setPrivatePipe(pipe);
        superpair.setGroupePipe(pipe);
        superpair.setSuperPipe(pipe);
        superpair.setSuperPipeAdv(pipeSuperAdv);
        superpair.setPrivatePipeAdv(pipePriveAdv);
        superpair.setGroupePipeAdv(pipeGroupeAdv);


        Groupe groupe = new Groupe(nomGroupe, superpair, subgroup);
        superpair.setMonGroupe(groupe);

        superpair.run();
    }

    private void createPair(String str[]) throws IOException, JxtaException {
        // On récupère le pipe de groupe donné dans le message
        PipeAdvertisement pipeGroupeAdv = null;
        if (str.length == 5) {
            pipeGroupeAdv = createPipeAdv(str[2], str[3], str[4]); // Creer le pipe.adv de groupe pour parler au groupe :)
        }

        // Création d'un pipe privé
        PipeAdvertisement pipePriveAdv = null;
        FileInputStream is1;
        try {
            is1 = new FileInputStream(pipePriveName);
            pipePriveAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8, is1);
            is1.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CreerRejoindreGroupe2.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Creer un pair avec le pipe de groupe et un nouveau pipe perso
        Pair pair = new Pair(jxtaConfig.getPeerName());
        pair.setPrivatePipe(pipe);
        pair.setGroupePipe(pipe);
        pair.setPrivatePipeAdv(pipePriveAdv);
        pair.setGroupePipeAdv(pipeGroupeAdv);
        pair.run();
    }

    public DiscoveryService getDiscoSvc() {
        return discoSvc;
    }

    public void setDiscoSvc(DiscoveryService discoSvc) {
        this.discoSvc = discoSvc;
    }

    public String getPipePriveName() {
        return pipePriveName;
    }

    public void setPipePriveName(String pipePriveName) {
        this.pipePriveName = pipePriveName;
    }

    public PipeService getPipe() {
        return pipe;
    }

    public void setPipe(PipeService pipe) {
        this.pipe = pipe;
    }
}
